home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 2 / Meeting Pearls Vol. II (1995)(GTI - Schatztruhe)[!].iso / Pearls / gfx / pbm / source / jpegV5.lha / jpegV5 / src / wrppm.c < prev    next >
C/C++ Source or Header  |  1994-12-23  |  8KB  |  249 lines

  1. /*
  2.  * wrppm.c
  3.  *
  4.  * Copyright (C) 1991-1994, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file contains routines to write output images in PPM/PGM format.
  9.  * The PBMPLUS library is NOT required to compile this software
  10.  * (but it is highly useful as a set of PPM image manipulation programs).
  11.  *
  12.  * These routines may need modification for non-Unix environments or
  13.  * specialized applications.  As they stand, they assume output to
  14.  * an ordinary stdio stream.
  15.  */
  16.  
  17. #include "cdjpeg.h"        /* Common decls for cjpeg/djpeg applications */
  18.  
  19. #ifdef PPM_SUPPORTED
  20.  
  21.  
  22. /*
  23.  * Currently, this code only knows how to write raw PPM or PGM format,
  24.  * which can be no more than 8 bits/sample.  As an expedient for testing
  25.  * 12-bit JPEG mode, we support writing 12-bit data to an 8-bit file by
  26.  * downscaling the values.  Of course this implies loss of precision.
  27.  * (When the core library supports data precision reduction, a cleaner
  28.  * implementation will be to ask for that instead.)
  29.  */
  30.  
  31. #if BITS_IN_JSAMPLE == 8
  32. #define DOWNSCALE(x)  (x)
  33. #else
  34. #define DOWNSCALE(x)  ((x) >> (BITS_IN_JSAMPLE-8))
  35. #endif
  36.  
  37.  
  38. /*
  39.  * When JSAMPLE is the same size as char, we can just fwrite() the
  40.  * decompressed data to the PPM or PGM file.  On PCs, in order to make this
  41.  * work the output buffer must be allocated in near data space, because we are
  42.  * assuming small-data memory model wherein fwrite() can't reach far memory.
  43.  * If you need to process very wide images on a PC, you might have to compile
  44.  * in large-memory model, or else replace fwrite() with a putc() loop ---
  45.  * which will be much slower.
  46.  */
  47.  
  48.  
  49. /* Private version of data destination object */
  50.  
  51. typedef struct {
  52.   struct djpeg_dest_struct pub;    /* public fields */
  53.  
  54.   /* Usually these two pointers point to the same place: */
  55.   char *iobuffer;        /* fwrite's I/O buffer */
  56.   JSAMPROW pixrow;        /* decompressor output buffer */
  57.  
  58.   JDIMENSION buffer_width;    /* width of one row */
  59. } ppm_dest_struct;
  60.  
  61. typedef ppm_dest_struct * ppm_dest_ptr;
  62.  
  63.  
  64. /*
  65.  * Write some pixel data.
  66.  * In this module rows_supplied will always be 1.
  67.  *
  68.  * put_pixel_rows handles the "normal" 8-bit case where the decompressor
  69.  * output buffer is physically the same as the fwrite buffer.
  70.  */
  71.  
  72. METHODDEF void
  73. put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
  74.         JDIMENSION rows_supplied)
  75. {
  76.   ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
  77.  
  78.   (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
  79. }
  80.  
  81.  
  82. /*
  83.  * This code is used when we have to copy the data because JSAMPLE is not
  84.  * the same size as char.  Typically this only happens in 12-bit mode.
  85.  */
  86.  
  87. METHODDEF void
  88. copy_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
  89.          JDIMENSION rows_supplied)
  90. {
  91.   ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
  92.   register char * bufferptr;
  93.   register JSAMPROW ptr;
  94.   register JDIMENSION col;
  95.  
  96.   ptr = dest->pub.buffer[0];
  97.   bufferptr = dest->iobuffer;
  98.   for (col = dest->buffer_width; col > 0; col--) {
  99.     *bufferptr++ = (char) DOWNSCALE(GETJSAMPLE(*ptr++));
  100.   }
  101.   (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
  102. }
  103.  
  104.  
  105. /*
  106.  * Write some pixel data when color quantization is in effect.
  107.  * We have to demap the color index values to straight data.
  108.  */
  109.  
  110. METHODDEF void
  111. put_demapped_rgb (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
  112.           JDIMENSION rows_supplied)
  113. {
  114.   ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
  115.   register char * bufferptr;
  116.   register int pixval;
  117.   register JSAMPROW ptr;
  118.   register JSAMPROW color_map0 = cinfo->colormap[0];
  119.   register JSAMPROW color_map1 = cinfo->colormap[1];
  120.   register JSAMPROW color_map2 = cinfo->colormap[2];
  121.   register JDIMENSION col;
  122.  
  123.   ptr = dest->pub.buffer[0];
  124.   bufferptr = dest->iobuffer;
  125.   for (col = cinfo->output_width; col > 0; col--) {
  126.     pixval = GETJSAMPLE(*ptr++);
  127.     *bufferptr++ = (char) DOWNSCALE(GETJSAMPLE(color_map0[pixval]));
  128.     *bufferptr++ = (char) DOWNSCALE(GETJSAMPLE(color_map1[pixval]));
  129.     *bufferptr++ = (char) DOWNSCALE(GETJSAMPLE(color_map2[pixval]));
  130.   }
  131.   (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
  132. }
  133.  
  134.  
  135. METHODDEF void
  136. put_demapped_gray (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
  137.            JDIMENSION rows_supplied)
  138. {
  139.   ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
  140.   register char * bufferptr;
  141.   register JSAMPROW ptr;
  142.   register JSAMPROW color_map = cinfo->colormap[0];
  143.   register JDIMENSION col;
  144.  
  145.   ptr = dest->pub.buffer[0];
  146.   bufferptr = dest->iobuffer;
  147.   for (col = cinfo->output_width; col > 0; col--) {
  148.     *bufferptr++ = (char) DOWNSCALE(GETJSAMPLE(color_map[GETJSAMPLE(*ptr++)]));
  149.   }
  150.   (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
  151. }
  152.  
  153.  
  154. /*
  155.  * Startup: write the file header.
  156.  */
  157.  
  158. METHODDEF void
  159. start_output_ppm (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
  160. {
  161.   ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
  162.  
  163.   /* Emit file header */
  164.   switch (cinfo->out_color_space) {
  165.   case JCS_GRAYSCALE:
  166.     /* emit header for raw PGM format */
  167.     fprintf(dest->pub.output_file, "P5\n%ld %ld\n%d\n",
  168.         (long) cinfo->output_width, (long) cinfo->output_height, 255);
  169.     break;
  170.   case JCS_RGB:
  171.     /* emit header for raw PPM format */
  172.     fprintf(dest->pub.output_file, "P6\n%ld %ld\n%d\n",
  173.         (long) cinfo->output_width, (long) cinfo->output_height, 255);
  174.     break;
  175.   default:
  176.     ERREXIT(cinfo, JERR_PPM_COLORSPACE);
  177.   }
  178. }
  179.  
  180.  
  181. /*
  182.  * Finish up at the end of the file.
  183.  */
  184.  
  185. METHODDEF void
  186. finish_output_ppm (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
  187. {
  188.   /* Make sure we wrote the output file OK */
  189.   fflush(dinfo->output_file);
  190.   if (ferror(dinfo->output_file))
  191.     ERREXIT(cinfo, JERR_FILE_WRITE);
  192. }
  193.  
  194.  
  195. /*
  196.  * The module selection routine for PPM format output.
  197.  */
  198.  
  199. GLOBAL djpeg_dest_ptr
  200. jinit_write_ppm (j_decompress_ptr cinfo)
  201. {
  202.   ppm_dest_ptr dest;
  203.  
  204.   /* Create module interface object, fill in method pointers */
  205.   dest = (ppm_dest_ptr)
  206.       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
  207.                   SIZEOF(ppm_dest_struct));
  208.   dest->pub.start_output = start_output_ppm;
  209.   dest->pub.finish_output = finish_output_ppm;
  210.  
  211.   /* Calculate output image dimensions so we can allocate space */
  212.   jpeg_calc_output_dimensions(cinfo);
  213.  
  214.   /* Create physical I/O buffer.  Note we make this near on a PC. */
  215.   dest->buffer_width = cinfo->output_width * cinfo->out_color_components;
  216.   dest->iobuffer = (char *)
  217.     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
  218.                 (size_t) (dest->buffer_width * SIZEOF(char)));
  219.  
  220.   if (cinfo->quantize_colors || SIZEOF(JSAMPLE) != SIZEOF(char)) {
  221.     /* When quantizing, we need an output buffer for colormap indexes
  222.      * that's separate from the physical I/O buffer.  We also need a
  223.      * separate buffer if JSAMPLE and char are not the same size.
  224.      */
  225.     dest->pub.buffer = (*cinfo->mem->alloc_sarray)
  226.       ((j_common_ptr) cinfo, JPOOL_IMAGE,
  227.        cinfo->output_width * cinfo->output_components, (JDIMENSION) 1);
  228.     dest->pub.buffer_height = 1;
  229.     if (! cinfo->quantize_colors)
  230.       dest->pub.put_pixel_rows = copy_pixel_rows;
  231.     else if (cinfo->out_color_space == JCS_GRAYSCALE)
  232.       dest->pub.put_pixel_rows = put_demapped_gray;
  233.     else
  234.       dest->pub.put_pixel_rows = put_demapped_rgb;
  235.   } else {
  236.     /* We will fwrite() directly from decompressor output buffer. */
  237.     /* Synthesize a JSAMPARRAY pointer structure */
  238.     /* Cast here implies near->far pointer conversion on PCs */
  239.     dest->pixrow = (JSAMPROW) dest->iobuffer;
  240.     dest->pub.buffer = & dest->pixrow;
  241.     dest->pub.buffer_height = 1;
  242.     dest->pub.put_pixel_rows = put_pixel_rows;
  243.   }
  244.  
  245.   return (djpeg_dest_ptr) dest;
  246. }
  247.  
  248. #endif /* PPM_SUPPORTED */
  249.